// Copyright (c) 2019 Presto Labs Pte. Ltd.
// Author: xguo

#pragma once

#include <experimental/filesystem>
#include <iostream>
#include <map>
#include <memory>
#include <set>
#include <string>

#include <nlohmann/json.hpp>

#define NOTREACHED() CHECK(false)

namespace coin::proto {
class ProductInfoProtoBundle;
class ProductInfoProto;
}  // namespace coin::proto

namespace coin2::exchange::base::symbology {

using ConstantContainer = nlohmann::json;

template <typename T>
bool HasValue(const ConstantContainer& container, const T& value) {
  for (auto it = container.begin(); it != container.end(); it++) {
    if (it.value() == value) {
      return true;
    }
  }
  return false;
}

class ProductInfoConstant {
 public:
  ProductInfoConstant() = default;
  explicit ProductInfoConstant(const std::experimental::filesystem::path& filename);
  ~ProductInfoConstant();

  const coin::proto::ProductInfoProto& GetProductInfo(const std::string& name) const;
  const coin::proto::ProductInfoProto& GetProductInfoByNativeSymbol(const std::string& name) const;
  bool HasNativeProduct(const std::string& native_product) const;
  bool HasNativeCurrency(const std::string& native_currency) const;
  bool HasNormCurrency(const std::string& norm_currency) const;
  const coin::proto::ProductInfoProtoBundle& GetProductInfoBundle() const;
  void MergeFrom(const ProductInfoConstant&);
  void PartialMergeFrom(const ProductInfoConstant& pi_const);
  void MergeExtraFrom(const ProductInfoConstant& pi_const);

 private:
  std::unique_ptr<coin::proto::ProductInfoProtoBundle> product_infos_;
  std::map<std::string, coin::proto::ProductInfoProto*> pi_map_;
  std::map<std::string, coin::proto::ProductInfoProto*> pi_map_native_;
  std::set<std::string> native_currencies_;
  std::set<std::string> norm_currencies_;
  std::set<std::string> native_products_;
};

}  // namespace coin2::exchange::base::symbology
